// 转坐标系编码
import proj4 from "proj4";
import {register} from "ol/proj/proj4";

import {addProjection, Projection} from "ol/proj";
import {getTopLeft, getWidth} from "ol/extent";
import WMTS from "ol/source/WMTS";
import WMTSTileGrid from "ol/tilegrid/WMTS";
import XYZ from "ol/source/XYZ";
import TileGrid from "ol/tilegrid/TileGrid";
import Asserts from "@/lang/core/asserts.js";

const proj4_version = 2.15;

/**
 * 注册 4490 大地坐标系
 */
const register4490 = () => {
    if (proj4_version > 2.8) {
        // 如果 版本 proj4 >= 2.8.0. 注册投影方式如下
        proj4.defs("EPSG:4490", "+proj=longlat +ellps=GRS80 +no_defs");
        register(proj4);
    } else {
        // 如果 版本 proj4 < 2.8.0. 注册投影方式如下
        // let projection_4490 = new ol.proj.Projection({
        //     code: "EPSG:4490",
        //     extent: [-180, -90, 180, 90],
        //     units: "metrem",
        //     axisOrientation: "neu",
        // });
        // ol.proj.addProjection(projection_4490);
        // proj4.defs("EPSG:4490", "+proj=longlat +ellps=GRS80 +no_defs +type=crs");
    }
}

// 直接进行注册
register4490();

// 转坐标系相关
let projection = new Projection({
    code: 'EPSG:4326',
    units: 'degrees',
    axisOrientation: 'neu'
});
projection.setExtent([-180, -90, 180, 90]);
projection.setWorldExtent([-180, -90, 180, 90]);
addProjection(projection);

let projectionExtent = projection.getExtent();

// size 指的是一个像素代表的经纬度
let size = getWidth(projectionExtent) / 256;


// 获取分辨率数组
//
// 这个只是针对 neu 坐标系，而我们注册的 4490 如果不重写定义 axisOrientation，
// 会被 ol 默认注册为 enu，从而不会触发 wms1.3.0 的反转 xy 的操作，导致图层无法加载，
// 所以需要进行 projection4490 的重写，然后覆盖添加到 projection 中。
let matrixIds = [];
let resolutions = [];
for (let z = 0; z < 20; ++z) {
    resolutions[z] = size / Math.pow(2, z);
    matrixIds[z] = z;
}

export default class Tianditu {
    static getProjection() {
        return projection
    }

    /**
     * 创建一个 WMTS 底图
     *
     * @param options
     * @returns {WMTS}
     */
    static createWMTS(options) {
        Asserts.notBlank(options.url, 'url is undefined!');

        const opts = {
            layer: "vec",
            matrixSet: "c",
            style: 'default',
            version: '1.0.0',
            crossOrigin: 'anonymous',
            format: 'tiles',
            wrapX: true,
            tileGrid: new WMTSTileGrid({
                origin: getTopLeft(projectionExtent),
                resolutions: resolutions,
                matrixIds: matrixIds
            })
        }

        Layers.copy(options, opts);
        return new WMTS(opts)
    }

    /**
     * 创建一个 XYZ 底图
     * @param options
     * @returns {XYZ}
     */
    static createXYZ(options) {
        Asserts.notBlank(options.url, 'url is undefined!');

        const url = options.url;
        delete options.url;
        const opts = {
            crossOrigin: 'anonymous',
            wrapX: true,
            //切片xyz获取方法
            tileUrlFunction: function (tileCoord) {
                const z = tileCoord[0];
                const x = tileCoord[1];
                const y = tileCoord[2];
                return url.replace('{z}', z.toString())
                    .replace('{y}', y.toString())
                    .replace('{x}', x.toString());
            },
            //坐标系
            projection: projection,
            tileGrid: new TileGrid({
                origin: getTopLeft(projectionExtent),
                tileSize: [256, 256],
                //分辨率数组
                resolutions: resolutions
            }),
        }

        Layers.copy(options, opts);
        return new XYZ(opts);
    }

}